#ifdef CH_LANG_CC
/*
 *      _______              __
 *     / ___/ /  ___  __ _  / /  ___
 *    / /__/ _ \/ _ \/  V \/ _ \/ _ \
 *    \___/_//_/\___/_/_/_/_.__/\___/
 *    Please refer to Copyright.txt, in Chombo's root directory.
 */
#endif

#ifndef _GAUSSIANSPHEREIF_H_
#define _GAUSSIANSPHEREIF_H_

#include "MayDay.H"
#include "RealVect.H"

#include "BaseIF.H"

#include "NamespaceHeader.H"

///
/**
    This implicit function specifies a sphere with gaussian spacing - the
    main use of this is for mollifying other implicit functions (see
    "MollifyIF").
 */
class GaussianSphereIF: public BaseIF
{
public:
  ///
  /**
      Constructor specifying gaussian sigma (a_sigma), center (a_center),
      and whether the domain is on the inside (a_inside).
   */
  GaussianSphereIF(const Real&     a_sigma,
                   const RealVect& a_center,
                   const bool&     a_inside);

  /// Copy constructor
  GaussianSphereIF(const GaussianSphereIF& a_inputIF);

  /// Destructor
  virtual ~GaussianSphereIF();

  ///
  /**
      Return the parameter information
   */
  virtual void GetParams(Real&     a_sigma,
                         RealVect& a_center,
                         bool&     a_inside) const;

  ///
  /**
      Set the parameter information
   */
  virtual void SetParams(const Real&     a_sigma,
                         const RealVect& a_center,
                         const bool&     a_inside);

  ///
  /**
      Return the value of the function at a_point.
   */
  virtual Real value(const RealVect& a_point) const;

  ///
  virtual Real derivative(const  IntVect& a_deriv,
                          const RealVect& a_point) const;

  ///
  virtual Real firstDeriv(const  IntVect& a_deriv,
                          const RealVect& a_point) const;

  ///
  virtual Real secondDeriv(const  IntVect& a_deriv,
                           const RealVect& a_point) const;

  ///
  virtual Real thirdDeriv(const  IntVect& a_deriv,
                           const RealVect& a_point) const;

  ///
  virtual Real fourthDeriv(const  IntVect& a_deriv,
                           const RealVect& a_point) const;

  ///
  virtual Real fifthDeriv(const  IntVect& a_deriv,
                          const RealVect& a_point) const;
  ///
  virtual Real sixthDeriv(const  IntVect& a_deriv,
                          const RealVect& a_point) const;

  virtual BaseIF* newImplicitFunction() const;

protected:
  Real     m_sigma;     // sigma
  RealVect m_center;    // center
  bool     m_inside;    // inside flag

  Real     m_sigma2;    // precomputed sigma squared
  Real     m_normal;    // precomputed normalizing factor

  //precomputed stuff for derivs
  /// m_b = 1/(2*sigma*sigma)
  /// m_C = m_normal
  Real m_b, m_C;
private:
  GaussianSphereIF()
  {
    MayDay::Abort("GaussianSphereIF uses strong construction");
  }

  void operator=(const GaussianSphereIF& a_inputIF)
  {
    MayDay::Abort("GaussianSphereIF doesn't allow assignment");
  }
};

#include "NamespaceFooter.H"
#endif
